home *** CD-ROM | disk | FTP | other *** search
- /*
- * fsdmDisk.c --
- *
- * Routines related to managing local disks domains. Each partition of
- * a local disk (partitions are defined by a table on the disk header) is
- * called a ``domain''. Fsdm_AttachDisk attaches a domain into the file
- * system, and FsDeattachDisk removes it. A domain is given
- * a number the first time it is ever attached. This is recorded on
- * the disk so it doesn't change between boots. The domain number is
- * used to identify disks, and a domain number plus a file number is
- * used to identify files. Fsdm_DomainFetch is used to get the state
- * associated with a disk, and Fsdm_DomainRelease releases the reference
- * on the state. Fsdm_DetachDisk checks the references on domains in
- * the normal (non-forced) case so that active disks aren't detached.
- *
- * Copyright 1987 Regents of the University of California
- * All rights reserved.
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fsdm/fsdmDisk.c,v 9.13 91/01/09 13:00:03 mgbaker Exp $ SPRITE (Berkeley)";
- #endif not lint
-
-
- #include "sprite.h"
-
- #include "fs.h"
- #include "fsutil.h"
- #include "fsconsist.h"
- #include "fsdm.h"
- #include "fslcl.h"
- #include "fsNameOps.h"
- #include "fsio.h"
- #include "fsprefix.h"
- #include "devDiskLabel.h"
- #include "dev.h"
- #include "devFsOpTable.h"
- #include "sync.h"
- #include "rpc.h"
- #include "fsioDevice.h"
- #include "fsdmInt.h"
- #include "string.h"
- #include "fscache.h"
-
-
- #include "ofs.h"
- #include "lfs.h"
-
-
- /*
- * A table of domains indexed by domain number. For use by a server
- * to map from domain number to info about the domain.
- */
- Fsdm_Domain *fsdmDomainTable[FSDM_MAX_LOCAL_DOMAINS];
- static int domainTableIndex = 0;
-
- Sync_Lock domainTableLock = Sync_LockInitStatic("Fs:domainTableLock");
- #define LOCKPTR (&domainTableLock)
-
- /*
- * Data structure will list of registered disk storage managers and their
- * attach procedures. This list is stored as an array and used in the
- * Fsdm_AttachDisk procedure.
- */
-
- typedef struct StorageManagerList {
- char *typeName; /* Name of storage manager type. */
- ReturnStatus (*attachProc) _ARGS_((Fs_Device *devicePtr,
- char *localName, int flags, int *domainNumPtr));
- /* Disk attach procedure. */
- } StorageManagerList;
-
- #define MAX_STORAGE_MANAGER_TYPES 4
- static StorageManagerList storageManagers[MAX_STORAGE_MANAGER_TYPES];
-
- static int numStorageManagers = 0; /* Number of storage managers. */
- /*
- * Forward declarations.
- */
- static Boolean OkToDetach _ARGS_((Fsdm_Domain *domainPtr));
- static void MarkDomainDown _ARGS_((Fsdm_Domain *domainPtr));
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_RegisterDiskManager --
- *
- * Register the attach procedure of a disk storage manager.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Attach procedure added to list.
- *
- *----------------------------------------------------------------------
- */
- void
- Fsdm_RegisterDiskManager(typeName, attachProc)
- char *typeName; /* Storage manger type name. */
- ReturnStatus (*attachProc) _ARGS_((Fs_Device *devicePtr,
- char *localName, int flags, int *domainNumPtr));
- /* Disk attach procedure. */
- {
- LOCK_MONITOR;
-
- if (numStorageManagers >= MAX_STORAGE_MANAGER_TYPES) {
- UNLOCK_MONITOR;
- panic("Fsdm_RegisterDiskManager: Can't register %s, %s (%d)\n",
- typeName, "Too many disk storage managers registered",
- numStorageManagers);
- return;
- }
- storageManagers[numStorageManagers].typeName = typeName;
- storageManagers[numStorageManagers].attachProc = attachProc;
- numStorageManagers++;
- UNLOCK_MONITOR;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_AttachDiskByHandle --
- *
- * Make a particular open Handle correspond to a prefix. Calls
- * Fsdm_AttachDisk to do real work.
- *
- * Results:
- * The SUCCESS if disk attach otherwise a Sprite return status.
- *
- * Side effects:
- * Many - Those of Fsdm_AttachDisk.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Fsdm_AttachDiskByHandle(ioHandlePtr, localName, flags)
- Fs_HandleHeader *ioHandlePtr; /* Open device handle of domain. */
- char *localName; /* The local prefix for the domain */
- int flags; /* FS_ATTACH_READ_ONLY or FS_ATTACH_LOCAL */
- {
- Fsio_DeviceIOHandle *devHandlePtr = (Fsio_DeviceIOHandle *) ioHandlePtr;
- return Fsdm_AttachDisk(&devHandlePtr->device, localName, flags);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_AttachDisk --
- *
- * Make a particular local disk partition correspond to a prefix.
- * This makes sure the disk is up, reads the domain header,
- * and calls the initialization routine for the block I/O module
- * of the disk's driver. By the time this is called the device
- * initialization routines have already been called from Dev_Config
- * so the device driver knows how the disk is partitioned into
- * domains. This routine sees if the domain is formatted correctly,
- * and if so attaches it to the set of domains.
- *
- * Results:
- * SUCCESS if the disk was readable and had a good domain header.
- *
- * Side effects:
- * Sets up the Fsutil_DomainInfo for the domain.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fsdm_AttachDisk(devicePtr, localName, flags)
- register Fs_Device *devicePtr; /* Device info from I/O handle */
- char *localName; /* The local prefix for the domain */
- int flags; /* FS_ATTACH_READ_ONLY|FS_ATTACH_LOCAL
- * or FS_DEFAULT_DOMAIN */
- {
- ReturnStatus status; /* Error code */
- register Fsdm_Domain *domainPtr; /* Top level info for the domain stored
- * on the device */
- Fsio_FileIOHandle *handlePtr; /* Reference to file handle for root */
- Fs_FileID fileID;
- int domainNum; /* Domain number. */
- int prefixFlags; /* For installing the prefix */
- int devFlags; /* Device flags. */
- int useFlags; /* Use flags. */
- int i;
-
- /*
- * Open the raw disk device so we can grub around in the header info.
- */
- useFlags = (flags | FS_ATTACH_READ_ONLY) ? FS_READ : (FS_READ|FS_WRITE);
- status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].open)
- (devicePtr, useFlags, (Fs_NotifyToken) NIL, &devFlags);
- if (status != SUCCESS) {
- return(status);
- }
-
-
- /*
- * Attempt to attach the disk under the same domain number each time.
- * This is required if clients are to be able to re-open files.
- */
- domainNum = -1;
- for (i = 0; i < numStorageManagers; i++) {
- status = storageManagers[i].attachProc(devicePtr, localName, flags,
- &domainNum);
- #ifdef lint
- status = Ofs_AttachDisk(devicePtr, localName, flags, &domainNum);
- status = Lfs_AttachDisk(devicePtr, localName, flags, &domainNum);
- #endif /* lint */
- if (domainNum >= 0) {
- break;
- }
- }
- if (status != SUCCESS) {
- return status;
- }
- domainPtr = Fsdm_DomainFetch(domainNum, FALSE);
- if (domainPtr == (Fsdm_Domain *)NIL) {
- return(FAILURE);
- }
-
- fileID.type = FSIO_LCL_FILE_STREAM;
- fileID.serverID = rpc_SpriteID;
- fileID.major = domainNum;
- fileID.minor = FSDM_ROOT_FILE_NUMBER;
- /*
- * Now that the block I/O is set up we can read the file descriptor
- * of the root directory of the domain.
- */
- status = Fsio_LocalFileHandleInit(&fileID, localName,
- (Fsdm_FileDescriptor *) NIL, FALSE, &handlePtr);
- if (status != SUCCESS) {
- printf( "Fsdm_AttachDisk: %s - can't get root file handle (%x)\n",
- localName, status);
- domainPtr->flags |= FSDM_DOMAIN_DOWN;
- return(status);
- }
- Fsutil_HandleUnlock(handlePtr);
- /*
- * The attach will succeed from this point, so print out info..
- */
- printf("%s: devType %#x devUnit %#x\n", localName,
- devicePtr->type, devicePtr->unit);
- /*
- * Install a prefix for the domain. We always import it so that
- * we can get to the disk locally. Then we either keep the domain
- * private or export it depending on the flags argument.
- */
- prefixFlags = FSPREFIX_IMPORTED;
- if (flags & FS_ATTACH_LOCAL) {
- prefixFlags |= FSPREFIX_LOCAL;
- printf("local ");
- } else {
- prefixFlags |= FSPREFIX_EXPORTED;
- printf("exported ");
- }
- (void)Fsprefix_Install(localName, (Fs_HandleHeader *) handlePtr,
- FS_LOCAL_DOMAIN, prefixFlags);
-
- if (flags & FS_ATTACH_READ_ONLY) {
- printf("read only\n");
- } else {
- printf("\n");
- }
-
- /*
- * Make sure a name hash table exists now that we have a disk attached.
- */
- Fslcl_NameHashInit();
- Fsdm_DomainRelease(domainNum);
- return(SUCCESS);
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_DetachDisk --
- *
- * Remove a local domain from the set of accessible domains.
- *
- * Results:
- * SUCCESS if the domain was already attached and all the outstanding
- * file handles could be recalled.
- *
- * Side effects:
- * Clears the prefix table entry for the domain.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fsdm_DetachDisk(prefixName)
- char *prefixName; /* Name that the disk is attached under. */
- {
- Fs_HandleHeader *hdrPtr;
- char *lookupName;
- int domainType;
- Fsprefix *prefixPtr;
- Fs_FileID rootID;
- int serverID;
- int domain;
- register Fsdm_Domain *domainPtr;
- ReturnStatus status;
-
- /*
- * Find the domain to detach.
- */
- status = Fsprefix_Lookup(prefixName,
- FSPREFIX_EXACT | FSPREFIX_EXPORTED | FSPREFIX_LOCAL,
- rpc_SpriteID, &hdrPtr, &rootID, &lookupName,
- &serverID, &domainType, &prefixPtr);
- if (status != SUCCESS) {
- return(status);
- } else if (hdrPtr->fileID.type != FSIO_LCL_FILE_STREAM) {
- return(GEN_INVALID_ARG);
- }
- domain = hdrPtr->fileID.major;
- domainPtr = Fsdm_DomainFetch(domain, FALSE);
- if (domainPtr == (Fsdm_Domain *)NIL) {
- return(FS_DOMAIN_UNAVAILABLE);
- }
-
- /*
- * Recall dirty blocks from remote clients, and copy dirty file descriptors
- * into their cache blocks. Once done, don't allow any more dirty
- * blocks to enter the cache.
- */
- Fsconsist_GetAllDirtyBlocks(domain, TRUE);
- status = Fsutil_HandleDescWriteBack(FALSE, -1);
- if (status != SUCCESS) {
- printf( "Fsdm_DetachDisk: %s - handle write-back failed <%x>.\n",
- domainPtr->domainPrefix, status);
- }
- /*
- * Mark the domain and wait for other users of the domain to leave.
- * The user can interrupt this wait, at which point we bail out.
- */
- if (!OkToDetach(domainPtr)) {
- Fsdm_DomainRelease(domain);
- return(FS_FILE_BUSY);
- }
- /*
- * Nuke the prefix table entry. Actually, this closes the handle
- * and leaves the prefix entry with no handle.
- */
- Fsprefix_HandleClose(prefixPtr, FSPREFIX_EXPORTED);
- /*
- * Write all dirty blocks, bitmaps, etc. to disk and take the
- * domain down.
- */
- status = domainPtr->domainOpsPtr->detachDisk(domainPtr);
- MarkDomainDown(domainPtr);
- return(status);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_DomainWriteBack --
- *
- * Force all domain information to disk.
- *
- * Results:
- * Error code if the write failed.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- Fsdm_DomainWriteBack(domain, shutdown, detach)
- int domain; /* Domain number, -1 means all domains */
- Boolean shutdown; /* TRUE if are syncing to shutdown the system.*/
- Boolean detach; /* TRUE if are writing back as part of
- * detaching the domain. This is used to force
- * the domain fetch to work even if it is
- * marked as down. */
- {
- register Fsdm_Domain *domainPtr;
- int firstDomain;
- register int lastDomain;
- register int i;
-
- if (domain >= 0) {
- /*
- * Write back a particular domain.
- */
- firstDomain = domain;
- lastDomain = domain;
- } else {
- /*
- * Write back all domains.
- */
- firstDomain = 0;
- lastDomain = FSDM_MAX_LOCAL_DOMAINS - 1;
- detach = FALSE;
- }
- for (i = firstDomain; i <= lastDomain; i++) {
- domainPtr = Fsdm_DomainFetch(i, detach);
- if (domainPtr != (Fsdm_Domain *) NIL) {
- (void ) domainPtr->domainOpsPtr->writeBack(domainPtr, shutdown);
- #ifdef lint
- (void) Ofs_DomainWriteBack(domainPtr, shutdown);
- (void) Lfs_DomainWriteBack(domainPtr, shutdown);
- #endif /* lint */
- Fsdm_DomainRelease(i);
- }
- }
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_InstallDomain --
- *
- * Install a Fsdm_Domain structure for a newly attached local domain and
- * save it in the domain table. The index into this table is
- * returned and passed around as the identifier for the domain.
- *
- * Results:
- * The domain number.
- *
- * Side effects:
- * Save the info in fsVolumeTable
- *
- *----------------------------------------------------------------------
- */
- ENTRY ReturnStatus
- Fsdm_InstallDomain(domainNumber, serverID, prefixName, flags, domainPtrPtr)
- int domainNumber; /* Domain nubmer to use. */
- int serverID; /* Server ID from disk. */
- char *prefixName; /* Prefix of domain. */
- int flags; /* Domain flags. */
- Fsdm_Domain **domainPtrPtr; /* OUT: Return domain pointer. */
- {
- Fsdm_Domain *oldDomainPtr, *domainPtr;
-
- LOCK_MONITOR;
-
- if (domainNumber == -1) {
- while ((domainTableIndex < FSDM_MAX_LOCAL_DOMAINS) &&
- (fsdmDomainTable[domainTableIndex] != (Fsdm_Domain *)NIL)) {
- domainTableIndex++;
- }
- if (domainTableIndex == FSDM_MAX_LOCAL_DOMAINS) {
- printf("Fsdm_InstallDomain: too many local domains.\n");
- domainNumber = -1;
- UNLOCK_MONITOR;
- return(FS_DOMAIN_UNAVAILABLE);
- }
- domainNumber = domainTableIndex;
- domainTableIndex++;
- }
- if ((domainNumber < 0) || (domainNumber >= FSDM_MAX_LOCAL_DOMAINS)) {
- printf("Fsdm_InstallDomain: domain number (%d) for %s out of range.\n",
- domainNumber, prefixName);
- UNLOCK_MONITOR;
- return(FS_DOMAIN_UNAVAILABLE);
- }
-
- oldDomainPtr = fsdmDomainTable[domainNumber];
- if (oldDomainPtr != (Fsdm_Domain *)NIL) {
- if (!(oldDomainPtr->flags & FSDM_DOMAIN_DOWN)) {
- printf("Fsdm_AttachDisk: %s already attached at domain %d\n",
- oldDomainPtr->domainPrefix, domainNumber);
- *domainPtrPtr = oldDomainPtr;
- UNLOCK_MONITOR;
- return(FS_FILE_BUSY);
- }
- domainPtr = oldDomainPtr;
- } else {
- domainPtr = (Fsdm_Domain *) malloc(sizeof(Fsdm_Domain));
- bzero((char *) domainPtr, sizeof(Fsdm_Domain));
- fsdmDomainTable[domainNumber] = domainPtr;
- }
- domainPtr->domainPrefix = malloc(strlen(prefixName)+1);
- (void)strcpy(domainPtr->domainPrefix, prefixName);
-
- domainPtr->domainNumber = domainNumber;
- domainPtr->flags = 0;
-
- *domainPtrPtr = domainPtr;
-
- if (rpc_SpriteID == 0) {
- /*
- * Use the spriteID on the 1st disk if we don't know it by now.
- * This is the last resort. Usually reverse arp or the hook
- * in the RPC protocol have established our ID. If there are
- * no other Sprite hosts running on the network , however,
- * then this code will execute.
- */
- printf(
- "Fsdm_InstallDomain: setting rpc_SpriteID to 0x%x from disk header\n",
- serverID);
- if (serverID <= 0) {
- panic("Bad sprite ID\n");
- }
- rpc_SpriteID = serverID;
- }
-
- if (flags & FS_DEFAULT_DOMAIN) {
- domainPtr->flags = FSDM_DOMAIN_ATTACH_BOOT;
- } else {
- domainPtr->flags = 0;
- }
- UNLOCK_MONITOR;
-
- return SUCCESS;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * OkToDetach --
- *
- * Wait for activity in a domain to end and then mark the
- * domain as being down. This prints a warning message and
- * waits in an interruptable state if the domain is in use.
- * Our caller should back out if we return FALSE.
- *
- * Results:
- * TRUE if it is ok to detach the domain.
- *
- * Side effects:
- * The FSDM_DOMAIN_GOING_DOWN flag is set in the domain.
- *
- *----------------------------------------------------------------------
- */
- static ENTRY Boolean
- OkToDetach(domainPtr)
- Fsdm_Domain *domainPtr;
- {
- LOCK_MONITOR;
-
- domainPtr->flags |= FSDM_DOMAIN_GOING_DOWN;
- /*
- * Wait until we are the only user of the domain because
- * noone else but the cache block cleaner or us should be using this
- * domain once we set this flag.
- */
- while (domainPtr->refCount > 1) {
- printf("Waiting for busy domain \"%s\"\n",
- domainPtr->domainPrefix);
- if (Sync_Wait(&domainPtr->condition, TRUE)) {
- domainPtr->flags &= ~FSDM_DOMAIN_GOING_DOWN;
- UNLOCK_MONITOR;
- return(FALSE); /* Interrupted while waiting, domain busy */
- }
- }
-
- UNLOCK_MONITOR;
- return(TRUE);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * MarkDomainDown --
- *
- * Mark the domain as being down.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The FSDM_DOMAIN_DOWN flag is set.
- *
- *----------------------------------------------------------------------
- */
- static ENTRY void
- MarkDomainDown(domainPtr)
- Fsdm_Domain *domainPtr;
- {
- LOCK_MONITOR;
-
- domainPtr->flags |= FSDM_DOMAIN_DOWN;
- if (domainPtr->refCount > 1) {
- printf("DomainDown: Refcount > 1\n");
- }
- domainPtr->refCount = 0;
-
- UNLOCK_MONITOR;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_DomainFetch --
- *
- * Return a pointer to the given domain if it is available.
- *
- * Results:
- * Pointer to the domain.
- *
- * Side effects:
- * Reference count in the domain incremented.
- *
- *----------------------------------------------------------------------
- */
- ENTRY Fsdm_Domain *
- Fsdm_DomainFetch(domain, dontStop)
- int domain; /* Domain to fetch. */
- Boolean dontStop; /* Fetch this domain unless it has been
- * totally detached. */
- {
- register Fsdm_Domain *domainPtr;
-
- LOCK_MONITOR;
-
- if (domain < 0 || domain >= FSDM_MAX_LOCAL_DOMAINS) {
- printf( "Fsdm_DomainFetch, bad domain number <%d>\n",
- domain);
- domainPtr = (Fsdm_Domain *)NIL;
- } else {
- domainPtr = fsdmDomainTable[domain];
- }
- if (domainPtr != (Fsdm_Domain *) NIL) {
- if (domainPtr->flags & FSDM_DOMAIN_DOWN) {
- domainPtr = (Fsdm_Domain *) NIL;
- } else if (dontStop || !(domainPtr->flags & FSDM_DOMAIN_GOING_DOWN)) {
- domainPtr->refCount++;
- } else {
- domainPtr = (Fsdm_Domain *) NIL;
- }
- }
-
- UNLOCK_MONITOR;
- return(domainPtr);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_DomainRelease --
- *
- * Release access to the given domain using a domain number.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Reference count for the domain decremented.
- *
- *----------------------------------------------------------------------
- */
- ENTRY void
- Fsdm_DomainRelease(domainNum)
- int domainNum;
- {
- register Fsdm_Domain *domainPtr;
-
- LOCK_MONITOR;
-
- domainPtr = fsdmDomainTable[domainNum];
- if (domainPtr == (Fsdm_Domain *)NIL) {
- panic( "Fsdm_DomainRelease: NIL domain pointer\n");
- }
-
- domainPtr->refCount--;
- if (domainPtr->refCount < 0) {
- panic( "Fsdm_DomainRelease: Negative ref count on domain %d\n",
- domainNum);
- }
- if (domainPtr->refCount == 0) {
- Sync_Broadcast(&domainPtr->condition);
- }
-
- UNLOCK_MONITOR;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_IsSunLabel --
- *
- * Poke around in the input buffer and see if it looks like
- * a Sun format disk label.
- *
- * Results:
- * TRUE or FALSE
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- Boolean
- Fsdm_IsSunLabel(buffer)
- Address buffer; /* Buffer containing zero'th sector */
- {
- register Sun_DiskLabel *sunLabelPtr;
-
- sunLabelPtr = (Sun_DiskLabel *)buffer;
- if (sunLabelPtr->magic == SUN_DISK_MAGIC) {
- /*
- * Should check checkSum...
- */
- return(TRUE);
- } else {
- return(FALSE);
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_IsSpriteLabel --
- *
- * Poke around in the input buffer and see if it looks like
- * a Sprite format disk header.
- *
- * Results:
- * TRUE or FALSE
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- Boolean
- Fsdm_IsSpriteLabel(buffer)
- Address buffer; /* Buffer containing zero'th sector */
- {
- register Fsdm_DiskHeader *diskHeaderPtr;
- register int index;
- register int checkSum;
- int *headerPtr;
-
- diskHeaderPtr = (Fsdm_DiskHeader *)buffer;
- if (diskHeaderPtr->magic == FSDM_DISK_MAGIC) {
- /*
- * Check the checkSum which set so that an XOR of all the
- * ints in the disk header comes out to FSDM_DISK_MAGIC also.
- */
- checkSum = 0;
- for (index = 0, headerPtr = (int *)buffer;
- index < DEV_BYTES_PER_SECTOR;
- index += sizeof(int), headerPtr++) {
- checkSum ^= *headerPtr;
- }
- if (checkSum == FSDM_DISK_MAGIC) {
- return(TRUE);
- } else {
- printf("IsSpriteLabel: checksum mismatch <%x>\n", checkSum);
- }
- }
- return(FALSE);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_IsDecLabel --
- *
- * Poke around in the input buffer and see if it looks like
- * a Dec format disk label.
- *
- * Results:
- * TRUE or FALSE
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- Boolean
- Fsdm_IsDecLabel(buffer)
- Address buffer; /* Buffer containing zero'th sector */
- {
- register Dec_DiskLabel *decLabelPtr;
-
- decLabelPtr = (Dec_DiskLabel *)buffer;
- if (decLabelPtr->magic == DEC_LABEL_MAGIC) {
- if (decLabelPtr->spriteMagic == FSDM_DISK_MAGIC &&
- decLabelPtr->version == DEC_LABEL_VERSION) {
- return TRUE;
- } else {
- printf("Dec label version mismatch: %x vs %x\n",
- decLabelPtr->version, DEC_LABEL_VERSION);
- }
- }
- return(FALSE);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_Init --
- *
- * Initialized the disk management routines. This means initializing
- * the domain table to NIL.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Fsdm_Init()
- {
- register int index;
- for (index = 0; index < FSDM_MAX_LOCAL_DOMAINS; index++) {
- fsdmDomainTable[index] = (Fsdm_Domain *) NIL;
- }
- Ofs_Init();
- Lfs_Init();
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_RereadSummaryInfo --
- *
- * Reread the summary sector associated with the prefix and update
- * the domain information. This should be called if the summary
- * sector on the disk has been changed since the domain was attached.
- *
- * Results:
- * SUCCESS if the summary sector was read correctly and the
- * information was updated
- *
- * Side effects:
- * The summary sector information associated with the domain is
- * updated.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Fsdm_RereadSummaryInfo(prefixName)
- char *prefixName; /* Name that the disk is attached under. */
- {
- Fs_HandleHeader *hdrPtr;
- char *lookupName;
- int domainType;
- Fsprefix *prefixPtr;
- Fs_FileID rootID;
- int serverID;
- int domain;
- register Fsdm_Domain *domainPtr;
- ReturnStatus status;
-
- /*
- * Find the correct domain.
- */
- status = Fsprefix_Lookup(prefixName,
- FSPREFIX_EXACT | FSPREFIX_EXPORTED | FSPREFIX_LOCAL,
- rpc_SpriteID, &hdrPtr, &rootID, &lookupName, &serverID,
- &domainType, &prefixPtr);
- if (status != SUCCESS) {
- return(status);
- } else if (hdrPtr->fileID.type != FSIO_LCL_FILE_STREAM) {
- return(GEN_INVALID_ARG);
- }
- domain = hdrPtr->fileID.major;
- domainPtr = Fsdm_DomainFetch(domain, FALSE);
- if (domainPtr == (Fsdm_Domain *)NIL) {
- return(FS_DOMAIN_UNAVAILABLE);
- }
- /*
- * Read the summary sector.
- */
- status = domainPtr->domainOpsPtr->rereadSummary(domainPtr);
- #ifdef lint
- status = Lfs_RereadSummaryInfo(domainPtr);
- status = Ofs_RereadSummaryInfo(domainPtr);
- #endif /* lint */
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_FileBlockRead --
- *
- * Read in a cache block.
- *
- * Results:
- * The results of the disk read.
- *
- * Side effects:
- * The buffer is filled with the number of bytes indicated by
- * the bufSize parameter. The blockPtr->blockSize is modified to
- * reflect how much data was actually read in. The unused part
- * of the block is filled with zeroes so that higher levels can
- * always assume the block has good stuff in all parts of it.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- Fsdm_FileBlockRead(hdrPtr, blockPtr, remoteWaitPtr)
- Fs_HandleHeader *hdrPtr; /* Handle on a local file. */
- Fscache_Block *blockPtr; /* Cache block to read in. This assumes
- * the blockNum, blockAddr (buffer area)
- * and blockSize are set. This modifies
- * blockSize if less bytes were read
- * because of EOF. */
- Sync_RemoteWaiter *remoteWaitPtr; /* NOTUSED */
- {
- register Fsio_FileIOHandle *handlePtr = (Fsio_FileIOHandle *)hdrPtr;
- register Fsdm_Domain *domainPtr;
- ReturnStatus status;
-
- domainPtr = Fsdm_DomainFetch(handlePtr->hdr.fileID.major, FALSE);
- if (domainPtr == (Fsdm_Domain *) NIL) {
- return(FS_DOMAIN_UNAVAILABLE);
- }
-
- status = domainPtr->domainOpsPtr->fileBlockRead(domainPtr, handlePtr,
- blockPtr);
- #ifdef lint
- status = Lfs_FileBlockRead(domainPtr,handlePtr,blockPtr);
- status = Ofs_FileBlockRead(domainPtr,handlePtr,blockPtr);
- #endif /* lint */
- Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_FileBlockWrite --
- *
- * Write out a cache block.
- *
- * Results:
- * The return code from the driver, or FS_DOMAIN_UNAVAILABLE if
- * the domain has been un-attached.
- *
- * Side effects:
- * The device write.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- Fsdm_FileBlockWrite(hdrPtr, blockPtr, flags)
- Fs_HandleHeader *hdrPtr; /* I/O handle for the file. */
- Fscache_Block *blockPtr; /* Cache block to write out. */
- int flags; /* IGNORED */
- {
- register Fsio_FileIOHandle *handlePtr = (Fsio_FileIOHandle *)hdrPtr;
- register Fsdm_Domain *domainPtr;
- ReturnStatus status;
-
- domainPtr = Fsdm_DomainFetch(handlePtr->hdr.fileID.major, TRUE);
- if (domainPtr == (Fsdm_Domain *)NIL) {
- return(FS_DOMAIN_UNAVAILABLE);
- }
- status = domainPtr->domainOpsPtr->fileBlockWrite(domainPtr, handlePtr,
- blockPtr);
-
- #ifdef lint
- status = Lfs_FileBlockWrite(domainPtr,handlePtr,blockPtr);
- status = Ofs_FileBlockWrite(domainPtr,handlePtr,blockPtr);
- #endif /* lint */
- Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
- return(status);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_FileTrunc --
- *
- * Truncate a file.
- *
- * Results:
- * The return code from the driver, or FS_DOMAIN_UNAVAILABLE if
- * the domain has been un-attached.
- *
- * Side effects:
- * The device write.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- Fsdm_FileTrunc(hdrPtr, size, delete)
- Fs_HandleHeader *hdrPtr; /* I/O handle for the file. */
- int size; /* Size to truncate to. */
- Boolean delete; /* True if the file is being deleted. */
- {
- Fsio_FileIOHandle *handlePtr = (Fsio_FileIOHandle *) hdrPtr;
- register Fsdm_Domain *domainPtr;
- ReturnStatus status;
-
- domainPtr = Fsdm_DomainFetch(handlePtr->hdr.fileID.major, TRUE);
- if (domainPtr == (Fsdm_Domain *)NIL) {
- return(FS_DOMAIN_UNAVAILABLE);
- }
- status = domainPtr->domainOpsPtr->fileTrunc(domainPtr, handlePtr, size,
- delete);
-
- #ifdef lint
- status = Lfs_FileTrunc(domainPtr, handlePtr, size, delete);
- status = Ofs_FileTrunc(domainPtr, handlePtr, size, delete);
- #endif /* lint */
- Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_DomainInfo --
- *
- * Return info about the given domain.
- *
- * Results:
- * Error if can't get to the domain.
- *
- * Side effects:
- * The domain info struct is filled in.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fsdm_DomainInfo(fileIDPtr, domainInfoPtr)
- Fs_FileID *fileIDPtr;
- Fs_DomainInfo *domainInfoPtr;
- {
- int domain = fileIDPtr->major;
- ReturnStatus status;
- Fsdm_Domain *domainPtr;
-
- if (domain >= FSDM_MAX_LOCAL_DOMAINS) {
- return(FS_DOMAIN_UNAVAILABLE);
- }
-
- domainPtr = Fsdm_DomainFetch(domain, FALSE);
- if (domainPtr == (Fsdm_Domain *) NIL) {
- return(FS_DOMAIN_UNAVAILABLE);
- }
- status = domainPtr->domainOpsPtr->domainInfo(domainPtr, domainInfoPtr);
- #ifdef lint
- status = Lfs_DomainInfo(domainPtr, domainInfoPtr);
- status = Ofs_DomainInfo(domainPtr, domainInfoPtr);
- #endif /* lint */
-
- Fsdm_DomainRelease(domain);
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_BlockAllocate --
- *
- * Allocate disk space for the given file. This routine only allocates
- * one block beginning at offset and going for numBytes. If
- * offset + numBytes crosses a block boundary then a panic will occur.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The file descriptor is modified to contain pointers to the allocated
- * blocks. Also *blockAddrPtr is set to the block that was allocated.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fsdm_BlockAllocate(hdrPtr, offset, numBytes, flags, blockAddrPtr, newBlockPtr)
- register Fs_HandleHeader *hdrPtr; /* Local file handle. */
- int offset; /* Offset to allocate at. */
- int numBytes; /* Number of bytes to allocate. */
- int flags; /* FSCACHE_DONT_BLOCK */
- int *blockAddrPtr; /* Disk address of block allocated. */
- Boolean *newBlockPtr; /* TRUE if there was no block allocated
- * before. */
- {
- Fsdm_Domain *domainPtr; /* Domain of file. */
- register Fsio_FileIOHandle *handlePtr; /* Local file handle. */
- ReturnStatus status;
-
- handlePtr = (Fsio_FileIOHandle *) hdrPtr;
- if (offset / FS_BLOCK_SIZE != (offset + numBytes - 1) / FS_BLOCK_SIZE) {
- panic("Fsdm_BlockAllocate - ALlocation spans block boundries\n");
- return FAILURE;
- }
- domainPtr = Fsdm_DomainFetch(handlePtr->hdr.fileID.major, TRUE);
- if (domainPtr == (Fsdm_Domain *)NIL) {
- return(FS_DOMAIN_UNAVAILABLE);
- }
- status = domainPtr->domainOpsPtr->blockAlloc(domainPtr, handlePtr,
- offset, numBytes, flags, blockAddrPtr, newBlockPtr);
- #ifdef lint
- status = Lfs_BlockAllocate(domainPtr, handlePtr, offset, numBytes, flags,
- blockAddrPtr, newBlockPtr);
- status = Ofs_BlockAllocate(domainPtr, handlePtr, offset, numBytes, flags,
- blockAddrPtr, newBlockPtr);
- #endif /* lint */
-
- Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_FindFileType --
- *
- * Map from flags in the handle to a constant corresponding to
- * the file type for the kernel.
- *
- * Results:
- * The value corresponding to the file's type is returned.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- int
- Fsdm_FindFileType(cacheInfoPtr)
- Fscache_FileInfo *cacheInfoPtr; /* File to determine type of */
- {
- switch (cacheInfoPtr->attr.userType) {
- case FS_USER_TYPE_TMP:
- return(FSUTIL_FILE_TYPE_TMP);
- case FS_USER_TYPE_SWAP:
- return(FSUTIL_FILE_TYPE_SWAP);
- case FS_USER_TYPE_OBJECT:
- return(FSUTIL_FILE_TYPE_DERIVED);
- case FS_USER_TYPE_BINARY:
- return(FSUTIL_FILE_TYPE_BINARY);
- default:
- return(FSUTIL_FILE_TYPE_OTHER);
- }
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_FileDescWriteBack --
- *
- * Force the file descriptor for the handle to disk.
- *
- * Results:
- * None.
- *
- * Side effects:
- * File descriptor block forced to disk.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fsdm_FileDescWriteBack(handlePtr, doWriteBack)
- Fsio_FileIOHandle *handlePtr; /* Handle that points
- * to descriptor to write back. */
- Boolean doWriteBack; /* Do a cache write back, not only
- * a store into the cache block. */
- {
- #ifdef NOTDEF
- Fs_HandleHeader *hdrPtr = (Fs_HandleHeader *) handlePtr;
- #endif NOTDEF
- register Fsdm_FileDescriptor *descPtr;
- register Fsdm_Domain *domainPtr;
- register ReturnStatus status = SUCCESS;
-
- domainPtr = Fsdm_DomainFetch(handlePtr->hdr.fileID.major, FALSE);
- if (domainPtr == (Fsdm_Domain *)NIL) {
- return(FS_DOMAIN_UNAVAILABLE);
- }
- descPtr = handlePtr->descPtr;
- if (descPtr == (Fsdm_FileDescriptor *)NIL) {
- if ((handlePtr->cacheInfo.flags & FSCACHE_FILE_GONE) == 0) {
- panic("Fsdm_FileDescWriteBack: no descriptor for \"%s\" (continuable)\n",
- Fsutil_HandleName(handlePtr));
- }
- status = FS_FILE_REMOVED;
- goto exit;
- }
- /*
- * If the handle times differ from the descriptor times then force
- * them out to the descriptor.
- */
- if (descPtr->accessTime < handlePtr->cacheInfo.attr.accessTime) {
- descPtr->accessTime = handlePtr->cacheInfo.attr.accessTime;
- #ifdef NOTDEF
- printf("Fsdm_FileDescWriteBack, access time changed <%d,%d> \"%s\"\n",
- hdrPtr->fileID.major, hdrPtr->fileID.minor,
- Fsutil_HandleName(hdrPtr));
- #endif
- descPtr->flags |= FSDM_FD_DIRTY;
- }
- if (descPtr->dataModifyTime < handlePtr->cacheInfo.attr.modifyTime) {
- descPtr->dataModifyTime = handlePtr->cacheInfo.attr.modifyTime;
- #ifdef NOTDEF
- printf("Fsdm_FileDescWriteBack, mod time changed <%d,%d> \"%s\"\n",
- hdrPtr->fileID.major, hdrPtr->fileID.minor,
- Fsutil_HandleName(hdrPtr));
- #endif
- descPtr->flags |= FSDM_FD_DIRTY;
- }
- if (descPtr->dataModifyTime > descPtr->descModifyTime) {
- descPtr->descModifyTime = descPtr->dataModifyTime;
- #ifdef NOTDEF
- printf("Fsdm_FileDescWriteBack, desc time changed <%d,%d> \"%s\"\n",
- hdrPtr->fileID.major, hdrPtr->fileID.minor,
- Fsutil_HandleName(hdrPtr));
- #endif
- descPtr->flags |= FSDM_FD_DIRTY;
- }
- if (descPtr->flags & FSDM_FD_DIRTY) {
- status = Fsdm_FileDescStore(handlePtr, doWriteBack);
- if (status != SUCCESS) {
- printf("Fsdm_FileDescWriteBack: Could not put desc <%d,%d> into cache\n",
- handlePtr->hdr.fileID.major,
- handlePtr->hdr.fileID.minor);
- }
- }
- exit:
- Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_DirOpStart --
- *
- * Mark the start of a directory operation.
- *
- * Results:
- *
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ClientData
- Fsdm_DirOpStart(opFlags, dirHandlePtr, dirOffset, name, nameLen, fileNumber,
- type, fileDescPtr)
- int opFlags; /* Operation code and flags. See fsdm.h for
- * definitions. */
- Fsio_FileIOHandle *dirHandlePtr; /* Handle of directory being operated
- * on. */
- int dirOffset; /* Byte offset into directory of the directory
- * entry containing operation. -1 if offset
- * is not known. */
- char *name; /* Name of object being operated on. */
- int nameLen; /* Length in characters of name. */
- int fileNumber; /* File number of objecting being operated on.*/
- int type; /* Type of the object being operated on. */
- Fsdm_FileDescriptor *fileDescPtr; /* FileDescriptor object being operated on
- * before operation starts. */
- {
- ClientData clientData;
- register Fsdm_Domain *domainPtr;
- domainPtr = Fsdm_DomainFetch(dirHandlePtr->hdr.fileID.major, FALSE);
- if (domainPtr == (Fsdm_Domain *)NIL) {
- return((ClientData) NIL);
- }
- opFlags |= FSDM_LOG_START_ENTRY;
- clientData = domainPtr->domainOpsPtr->dirOpStart(domainPtr, opFlags,
- name, nameLen, fileNumber, fileDescPtr,
- dirHandlePtr->hdr.fileID.minor, dirOffset,
- dirHandlePtr->descPtr);
- #ifdef lint
- clientData = Lfs_DirOpStart(domainPtr, opFlags,
- name, nameLen, fileNumber, fileDescPtr,
- dirHandlePtr->hdr.fileID.minor, dirOffset,
- dirHandlePtr->descPtr);
-
- clientData = Ofs_DirOpStart(domainPtr, opFlags,
- name, nameLen, fileNumber, fileDescPtr,
- dirHandlePtr->hdr.fileID.minor, dirOffset,
- dirHandlePtr->descPtr);
- #endif /* lint */
-
- Fsdm_DomainRelease(dirHandlePtr->hdr.fileID.major);
- return(clientData);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fsdm_DirOpEnd --
- *
- * Mark the end of a directory operation.
- *
- * Results:
- * None
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Fsdm_DirOpEnd(opFlags, dirHandlePtr, dirOffset, name, nameLen, fileNumber,
- type, fileDescPtr, clientData, status)
- int opFlags; /* Operation code and flags. See fsdm.h for
- * definitions. */
- Fsio_FileIOHandle *dirHandlePtr; /* Handle of directory being operated
- * on. */
- int dirOffset; /* Byte offset into directory of the directory
- * entry containing operation. -1 if offset
- * is not known. */
- char *name; /* Name of object being operated on. */
- int nameLen; /* Length in characters of name. */
- int fileNumber; /* File number of objecting being operated on.*/
- int type; /* Type of the object being operated on. */
- Fsdm_FileDescriptor *fileDescPtr; /* FileDescriptor object being operated on
- * before operation starts. */
- ClientData clientData; /* ClientData as returned by DirOpStart. */
- ReturnStatus status; /* Return status of the operation, SUCCESS if
- * operation succeeded. FAILURE otherwise. */
- {
- register Fsdm_Domain *domainPtr;
-
- domainPtr = Fsdm_DomainFetch(dirHandlePtr->hdr.fileID.major, FALSE);
- if (domainPtr == (Fsdm_Domain *)NIL) {
- return;
- }
- opFlags |= FSDM_LOG_END_ENTRY;
- domainPtr->domainOpsPtr->dirOpEnd(domainPtr, clientData, status, opFlags,
- name, nameLen, fileNumber, fileDescPtr,
- dirHandlePtr->hdr.fileID.minor, dirOffset,
- dirHandlePtr->descPtr);
- #ifdef lint
- Lfs_DirOpEnd(domainPtr, clientData, status, opFlags,
- name, nameLen, fileNumber, fileDescPtr,
- dirHandlePtr->hdr.fileID.minor, dirOffset,
- dirHandlePtr->descPtr);
-
- Ofs_DirOpEnd(domainPtr, clientData, status, opFlags,
- name, nameLen, fileNumber, fileDescPtr,
- dirHandlePtr->hdr.fileID.minor, dirOffset,
- dirHandlePtr->descPtr);
- #endif /* lint */
- Fsdm_DomainRelease(dirHandlePtr->hdr.fileID.major);
- return;
- }
-
-
-